﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ini;
using CAlisV6MQ;
using System.Xml;
using System.Xml.XPath;
using System.IO;
using CSequence.localhost;
using Microsoft.VisualBasic;
using System.Data.OleDb;


namespace CSequence
{
    public class CFileParameter
    {
        public string sName;
        public string sValue;
        public string sCalValue;
        public float fX;
        public float fY;
        public CStep m_Parent;
        public int iControlIndex;
        public string sID;
        public CFileParameter()
        {
        }

        public string ToXml()
        {
            string sRet;
            sRet = "<Name>" + sName  + "</Name>";
            sRet += "<Value>" + sValue + "</Value>";
            return sRet;
        }

        public CFileParameter(string sInName, string sInValue, string sInID)
        {
            sName = sInName;
            sValue = sInValue;
            sID = sInID;
        }

        public CFileParameter(string sSection)
        {
            string[] arrSec = sSection.Split('=');
            if (arrSec.Length == 1)
            {
                sName = arrSec[0];
                sValue = "";
            }
            else 
            {
                
                sName = arrSec[0];
                sValue = "";
                for (int i = 1; i < arrSec.Length; i++)
                {
                    if (i == (arrSec.Length-1)) 
                        sValue += arrSec[i];
                    else
                        sValue += arrSec[i] + "=";
                }

            }
        }
    }

    public class CInput : CFileParameter
    {
        
        public CInput(CStep oParent)
            : base()
        {
            m_Parent = oParent;
        }

        public CInput(string sSection, CStep oParent)
            : base(sSection)
        {
            m_Parent = oParent;
        }

        public CInput(string sInName,string sInPar,  string sInID,CStep oParent)
            : base(sInName, sInPar, sInID)
        {
            m_Parent = oParent;
        }

        public string ToSql()
        {
            string sRet;
            sRet = "insert into  T_API_QD_PROCESS_STEP_PARAMS (PROCESS_ID,STEP_ID,ID,PARAMS_TYPE, NAME, PARAM_VALUE ) ";
            sRet += "values (" + m_Parent.sProcessId + "," + m_Parent.sId + "," + sID + ",'I','" + sName + "','" + sValue + "');\r\n";
            return sRet;
        }
    }

    public class COutput : CFileParameter
    {
        public COutput()
            : base()
        {
        }

       public COutput(string sSection, CStep oParent)
            : base(sSection)
        {
            m_Parent = oParent;
        }

       public COutput(string sName, string sVal, string sInID, CStep oParent)
           : base(sName, sVal, sInID)
       {
           m_Parent = oParent;
       }

       public string ToSql()
       {
           string sRet;
           sRet = "insert into  T_API_QD_PROCESS_STEP_PARAMS (PROCESS_ID,STEP_ID,ID,PARAMS_TYPE, NAME, PARAM_VALUE ) ";
           sRet += "values (" + m_Parent.sProcessId + "," + m_Parent.sId + "," + sID + ",'O','" + sName + "','" + sValue + "');\r\n";
           return sRet;
       }

    }

    public class CParam : CFileParameter
    {
        public CParam()
            : base()
        {
        }

        public CParam(string sSection, CStep oParent)
            : base(sSection)
        {
            m_Parent = oParent;
        }

        public CParam(string sName, string sVal, string sInID, CStep oParent)
            : base(sName, sVal, sInID)
        {
            m_Parent = oParent;
        }
    }

    public class CDisplay : CFileParameter
    {

        public void Save()
        {
            //m_Parent.oIniFile.IniWriteValue("Display", sName, sValue);
        }

        public CDisplay(CStep oParent)
            : base()
        {
            m_Parent = oParent;
        }

        public CDisplay(string sSection, CStep oParent)
            : base(sSection)
        {
            m_Parent = oParent;

        }
        public CDisplay(string sName,string sVal, string sInID,CStep oParent)
            : base(sName, sVal, sInID)
        {
            m_Parent = oParent;

        }

        public string ToSql()
        {
            string sRet;
            sRet = "insert into  T_API_QD_PROCESS_STEP_PARAMS (PROCESS_ID,STEP_ID,ID,PARAMS_TYPE, NAME, PARAM_VALUE ) ";
            sRet += "values (" + m_Parent.sProcessId + "," + m_Parent.sId + "," + sID + ",'D','" + sName + "','" + sValue + "');\r\n";
            return sRet;
        }


    }

    public class CStep
    {
        public IniFile oIniFile = null;
        FileSequence m_FileSequence;
        public bool bCalculated;
        public int iControlIndex;
        public string sErrorCode="";
        public string sErrorMessage = "";
                
        public delegate void ChangedEventHandler(object sender, EventArgs e);
        public event ChangedEventHandler Calculated;
        public string sName;
        public string sDir;
        public string sQueryName;
        public string sType;
        public string sMode;
        public string sProcessId;
        public string sId;
        enum Serialise { XML, Ini, Database};
        Serialise eSerialise;
        OleDbConnection m_connection;

        public string sLastRunInXml="";
        public string sLastRunOutXml="";


        // List of the input and ouput params
        public List<CInput> lInputs = new List<CInput>();
        public List<COutput> lOutputs = new List<COutput>();
        public List<CParam> lParams = new List<CParam>();
        public List<CDisplay> lDisplay = new List<CDisplay>();

        public void Save()
        {
            if (eSerialise == Serialise.XML)
            {
                if (File.Exists(sDir + "\\" + sName + ".bak"))
                    File.Delete(sDir + "\\" + sName + ".bak");

                if (File.Exists(sDir + "\\" + sName + ".xml"))
                    File.Copy(sDir + "\\" + sName + ".xml", sDir + "\\" + sName + ".bak");

                StreamWriter writer = new StreamWriter(sDir + "\\" + sName + ".xml");
                writer.Write(ToXml());
                writer.Close();
            }
            else if (eSerialise == Serialise.Database)
            {
                string sSql = "Begin \r\n";
                sSql += "delete from T_API_QD_PROCESS_STEP where PROCESS_ID=" + sProcessId + " and ID=" + sId + ";\r\n";
                sSql += "delete from T_API_QD_PROCESS_STEP_PARAMS where PROCESS_ID=" + sProcessId + " and STEP_ID=" + sId + ";\r\n";
                sSql += ToSql();
                sSql += "end;";
                RunSql(sSql);
            }
        }

        private void RunSql(String sSql)
        {
            try
            {
                OleDbCommand command = new OleDbCommand(sSql, m_connection);
                int iRows = command.ExecuteNonQuery();
                command.Dispose();
            }
            catch (Exception ex)
            {
                //sText += ex.Message + " (" + sSql + ")\r\n";
            }
        }

        public string ToSql()
        {
            string sSql = "insert into  T_API_QD_PROCESS_STEP (PROCESS_ID,ID,NAME,TYPE,QUERY_NAME,STEP_MODE ) ";
            sSql += "values (" + sProcessId + "," + sId  + ",";
            sSql += "'" + sName.Replace("'","''") + "'," + GetType(sType) + " ,'" + sQueryName + "', '" + sMode + "');\r\n";
            
            foreach (CInput Input in lInputs)
                sSql += Input.ToSql();

            foreach (COutput Output in lOutputs)
                sSql += Output.ToSql();

            foreach (CDisplay Display in lDisplay)
                sSql += Display.ToSql();

            return sSql;
        }

        private string GetType(string sType)
        {
            string sRet="";
            switch (sType)
            {
                case "Constants":
                    sRet = "0";
                    break;
                case "QueryDef":
                    sRet = "1";
                    break;
                case "QueryDefUpdate":
                    sRet = "2";
                    break;
                case "UpdateQueryDef":
                    sRet = "2";
                    break;
                case "UpdateAlisWebService":
                    sRet = "3";
                    break;
                case "AlisWebService":
                    sRet = "4";
                    break;
                case "IF":
                    sRet = "5";
                    break;
                case "ELSE":
                    sRet = "6";
                    break;
                case "END IF":
                    sRet = "7";
                    break;
                case "FOR":
                    sRet = "8";
                    break;
                case "END FOR":
                    sRet = "9";
                    break;
                case "QueryDefProcess":
                    sRet = "10";
                    break;

            }
            return sRet;
        }

        public string ToXml() 
        {
            string sRet = "";
            sRet = "<Root>\r\n";
            sRet += " <Step Name=\"" + sName + "\" Mode=\"" + sMode + "\" Type=\"" + sType + "\" QueryName=\"" + sQueryName + "\">\r\n";
            
            sRet += "  ";
            foreach (CInput oIn in lInputs)
                sRet += "   <Input Name=\"" + oIn.sName + "\" Value=\"" + oIn.sValue+ "\"></Input>\r\n";
            
            foreach (COutput oOut in lOutputs)
                sRet += "   <Output Name=\"" + oOut.sName + "\" Value=\"" + oOut.sValue + "\"></Output>\r\n";

            foreach (CParam oPar in lParams)
                sRet += "   <Param Name=\"" + oPar.sName + "\" Value=\"" + oPar.sValue + "\"></Param>\r\n";

            foreach (CDisplay oDis in lDisplay)
                sRet += "   <Display Name=\"" + oDis.sName + "\" Value=\"" + oDis.sValue + "\"></Display>\r\n";
         

            sRet += " </Step>\r\n";
            sRet += "</Root>\r\n";
            return sRet;
        }

        public string GetInputValue(string sInName)
        {
            string sRet = "";
            CInput oIn = lInputs.Find(element => element.sName == sInName);
            if (oIn != null)
                sRet = oIn.sValue;

            return sRet;
        }

        public COutput FindOutput(string sName)
        {
            COutput oOut = lOutputs.Find(element => element.sName == sName);
            return oOut;
        }

        public CInput FindInput(string sName)
        {
            CInput oIn = lInputs.Find(element => element.sName == sName);
            return oIn;
        }

        public string GetInputCalValue(string sInName)
        {
            string sRet = "";
            CInput oIn = lInputs.Find(element => element.sName == sInName);
            if (oIn != null)
                sRet = oIn.sCalValue;

            return sRet;
        }

        public string GetOutputValue(string sOutName)
        {
            string sRet = "";
            COutput oOut = lOutputs.Find(element => element.sName == sOutName);
            if (oOut != null)
                sRet = oOut.sValue;

            return sRet;
        }

        public string GetDisplayValue(string sDisName)
        {
            string sRet = "";
            CDisplay oDis = lDisplay.Find(element => element.sName == sDisName);
            if (oDis != null)
                sRet = oDis.sValue;

            return sRet;
        }

        public string GetDisplayValue(string sDisName, string sDefault)
        {
            string sRet = sDefault;
            CDisplay oDis = lDisplay.Find(element => element.sName == sDisName);
            if (oDis != null)
                sRet = oDis.sValue;

            return sRet;
        }

        public void  SetDisplayValue(string sDisName, string sValue)
        {
            
            CDisplay oDis = lDisplay.Find(element => element.sName == sDisName);
            if (oDis != null)
            {
                oDis.sValue = sValue;
                m_FileSequence.bIsDirty = true;
            }
        }

        public CStep()
        {
            bCalculated = false;
        }

        public CStep(OleDbDataReader oDataReader, OleDbConnection oConnection, FileSequence oFileSequence)
        {
            
            try
            {
                eSerialise = Serialise.Database;
                m_FileSequence = oFileSequence;
                m_connection = oConnection;
                sProcessId  = oDataReader["PROCESS_ID"].ToString();
                switch (oDataReader["STYPE"].ToString())
                {
                    case "0":
                        sType = "Constants";
                        break;
                    case "1":
                        sType = "QueryDef";
                        break;
                    case "2":
                        sType = "QueryDefUpdate";
                        break;
                    case "3":
                        sType = "UpdateAlisWebService";
                        break;
                    case "4":
                        sType = "AlisWebService";
                        break;
                    case "5":
                        sType = "IF";
                        break;
                    case "6":
                        sType = "ELSE";
                        break;
                    case "7":
                        sType = "END IF";
                        break;
                    case "8":
                        sType = "FOR";
                        break;
                    case "9":
                        sType = "END FOR";
                        break;
                    case "10":
                        sType = "QueryDefProcess";
                        break;

                }

                sName       = oDataReader["NAME"].ToString();
                sQueryName  = oDataReader["QUERY_NAME"].ToString();
                sId         = oDataReader["ID"].ToString();
                sMode       = oDataReader["STEP_MODE"].ToString();
            }
            catch
            { 
            }
        }

        public CStep(string sInPath, FileSequence oFileSequence)
        {
            bCalculated = false;
            m_FileSequence = oFileSequence;
            string sFilePath = sInPath;
            
            sName = Path.GetFileName(sInPath);
            sDir = Path.GetDirectoryName(sInPath);

            XmlDocument oXmlDoc = new XmlDocument();
            oXmlDoc.Load(sInPath);
            XmlNode oNode = oXmlDoc.SelectSingleNode("/Root/Step/@Type");
            if (oNode != null)
                sType = oNode.Value;

            oNode = oXmlDoc.SelectSingleNode("/Root/Step/@Name");
            if (oNode != null)
                sName = oNode.Value;

            oNode = oXmlDoc.SelectSingleNode("/Root/Step/@Mode");
            if (oNode != null)
                sMode = oNode.Value;

            oNode = oXmlDoc.SelectSingleNode("/Root/Step/@QueryName");
            if (oNode != null)
                sQueryName = oNode.Value;

            XmlNodeList nodeList1 = oXmlDoc.SelectSingleNode("/Root/Step").SelectNodes("Input");
            int i = 0;
            foreach (XmlNode xName in nodeList1)
            {
                string sInName = xName.Attributes["Name"].Value;
                string sInValue = xName.Attributes["Value"].Value;
                if (sInName != null)
                {
                    CInput oIn = new CInput(sInName, sInValue,i.ToString(), this);
                    i++;
                    lInputs.Add(oIn);
                }
            }

            XmlNodeList nodeList2 = oXmlDoc.SelectSingleNode("/Root/Step").SelectNodes("Output");
            foreach (XmlNode xName in nodeList2)
            {
                COutput oOut = new COutput(xName.Attributes["Name"].Value, xName.Attributes["Value"].Value, i.ToString(), this);
                i++;
                lOutputs.Add(oOut);
            }

            XmlNodeList nodeList3 = oXmlDoc.SelectSingleNode("/Root/Step").SelectNodes("Param");
            foreach (XmlNode xName in nodeList3)
            {
                CParam oPar = new CParam(xName.Attributes["Name"].Value, xName.Attributes["Value"].Value, i.ToString(), this);
                i++;
                lParams.Add(oPar);
            }

            XmlNodeList nodeList4 = oXmlDoc.SelectSingleNode("/Root/Step").SelectNodes("Display");
            foreach (XmlNode xName in nodeList4)
            {
                CDisplay oDis = new CDisplay(xName.Attributes["Name"].Value, xName.Attributes["Value"].Value, i.ToString(), this);
                i++;
                lDisplay.Add(oDis);
            }
        }

        public override string ToString()
        {
            string sRet = " " + sName + "," + sType + "\r\n";

            foreach (CInput oIn in lInputs)
                sRet += " >" + oIn.sName + "," + oIn.sValue + "," + oIn.sCalValue + "\r\n";

            foreach (COutput oOut in lOutputs)
                sRet += " <" + oOut.sName + "," + oOut.sCalValue + "\r\n";

            foreach (CDisplay oDis in lDisplay)
                sRet += " @" + oDis.sName + "," + oDis.sValue + "\r\n";

            return sRet;
        }

        public void CalculateIf()
        {
            // An If step must have 3 inputs ( A == B)
            // A and B and inputs, the == is the operator
            string sOperator="", sA="", sB="";
            if (lInputs.Count < 2)
            {
                sErrorCode="2";
                sErrorMessage = "'If' step must have 2 or 3 Inputs";
            }
            else
            {

                sA = lInputs[0].sCalValue;
                sOperator = lInputs[1].sValue;
                // B os optional depending upon the sOperator
                if (lInputs.Count >= 3)
                    sB = lInputs[2].sValue;
         
                switch (sOperator.ToLower())
                {
                    case "==":
                    case "=":
                        if (sA != sB) m_FileSequence.bIfElseFlag = true;
                        break;
                    case "isnull":
                        if (sA != "") m_FileSequence.bIfElseFlag = true;
                        break;

                }
                bCalculated = true;                
            }
        }

        public void CalculateQueryDef()
        {
            CAlisV6MQ.CAlisV6MQ oCAlisV6MQ = new CAlisV6MQ.CAlisV6MQ();

            // Get all the Queue details
            IniFile oIniFile = new IniFile("C:\\Sapiens\\Sequence\\Sequence.ini");


            string sQueueManager  = oIniFile.IniReadValue("MQ", "QueueManager");
            string sChannel       = oIniFile.IniReadValue("MQ", "Channel");
            string sServer        = oIniFile.IniReadValue("MQ", "Server");  
            string sRequestQueue  = oIniFile.IniReadValue("MQ", "RequestQueue"); 
            string sResponseQueue = oIniFile.IniReadValue("MQ", "ResponseQueue");

            string sUserName   = oIniFile.IniReadValue("QDHeader", "UserName");
            string sToken      = oIniFile.IniReadValue("QDHeader", "Token");
            string sPassword   = oIniFile.IniReadValue("QDHeader", "Password");
            string sLanguageId = oIniFile.IniReadValue("QDHeader", "LanguageId");
            string sCompanyId  = oIniFile.IniReadValue("QDHeader", "CompanyId");


            string sSend = "<?xml version=\"1.0\" encoding=\"UTF8\"?><Root><XMLHeader><MethodName>QueryDef</MethodName><UserName>$UserName$</UserName>$Password$<LanguageId>$LanguageId$</LanguageId><CompanyId>$CompanyId$</CompanyId></XMLHeader><XMLBody><Queries><Query Name=\"";
            sSend = sSend.Replace("$UserName$", sUserName);
            if (sPassword == "")
                sSend = sSend.Replace("$Token$", "<Token>" + sToken + "</Token>");
            else
                sSend = sSend.Replace("$Password$", "<Password>" + sPassword + "</Password>");
            sSend = sSend.Replace("$LanguageId$", sLanguageId);
            sSend = sSend.Replace("$CompanyId$", sCompanyId);
            sSend += sQueryName + "\"";
            if ( sMode == "Debug")
                sSend += " Mode=\"1\" ";
            else if (sMode == "Schema")
                sSend += " Mode=\"2\" ";
            sSend += "><Param>\r\n";
            foreach (CInput oParam in lInputs)
            {
                sSend += "<" + oParam.sName + ">" + oParam.sValue + "</" + oParam.sName + ">\r\n";
            }

            sSend += "</Param></Query></Queries></XMLBody></Root>";

            oCAlisV6MQ.Init(sServer, sQueueManager, sRequestQueue, sResponseQueue, sChannel);
            string sRet = oCAlisV6MQ.SendAndGetMessage(sSend);
            sLastRunInXml = sSend; sLastRunOutXml = sRet;

            XmlDocument oXmlDoc = new XmlDocument();
            if (sRet.Length > 0)
            {
                oXmlDoc.LoadXml(sRet);
                foreach (COutput oOut in lOutputs)
                {                    
                    XmlNode oNode = oXmlDoc.SelectSingleNode(oOut.sValue);
                    if (oNode != null)
                        oOut.sCalValue = oNode.Value;
                }
                bCalculated = true;
            }
        }
        
        public string GetOutputFilename()
        {
            return m_FileSequence.sWorkingFolder + "\\Output\\" + sName + ".xml";
        }

        public void CalculateAlisWebService()
        {
            // Get all the Queue details 

            string sUserName = GetInputCalValue("UserName");
            string sToken = GetInputCalValue("Token");
            string sPassword = GetInputCalValue("Password");
            string sLanguageId = GetInputCalValue("LanguageId");
            string sCompanyId = GetInputCalValue("CompanyId");


            string sSend = "<?xml version=\"1.0\" encoding=\"UTF8\"?><Root><XMLHeader><MethodName>QueryDef</MethodName><UserName>$UserName$</UserName><Password>$Password$</Password><LanguageId>$LanguageId$</LanguageId><CompanyId>$CompanyId$</CompanyId></XMLHeader><XMLBody><Queries><Query Name=\"";
            sSend = sSend.Replace("$UserName$", sUserName);
            sSend = sSend.Replace("$Token$", sToken);
            sSend = sSend.Replace("$Password$", sPassword);
            sSend = sSend.Replace("$LanguageId$", sLanguageId);
            sSend = sSend.Replace("$CompanyId$", sCompanyId);
            sSend += sQueryName;
            sSend += "\">";

            foreach (CParam oPar in lParams)
            {
                //sSend += "<Name>$Name$</Name>";
               
            }
                
            sSend += "</Query></Queries></XMLBody></Root>";

            AlisWebService oWs = new AlisWebService();
            string sRet = "";
            try
            {
                sRet = oWs.putAndGetMessage(sSend);
                IniFile oIni = new Ini.IniFile(m_FileSequence.sWorkingFolder + "\\Stats.ini");
                oIni.IniWriteValue("Run-" + m_FileSequence.m_RunNum.ToString(), "CalculateAlisWebService-" + sName, DateTime.Now.ToString());

            }
            catch (Exception e)
            {
                m_FileSequence.sLastError = "Failed to call the AlisWebServices(" + e.Message + ")\r\n";
                IniFile oIni = new Ini.IniFile(m_FileSequence.sWorkingFolder + "\\Stats.ini");
                oIni.IniWriteValue("Run-" + m_FileSequence.m_RunNum.ToString(), "CalculateAlisWebServiceError(" + e.Message + ")-" + sName, DateTime.Now.ToString());
            }
            
            XmlDocument oXmlDoc = new XmlDocument();
            if (sRet.Length > 0)
            {
                oXmlDoc.LoadXml(sRet);

                foreach (COutput oOut in lOutputs)
                {
                    XmlNode oNode = oXmlDoc.SelectSingleNode(oOut.sValue);
                    if (oNode != null)
                        oOut.sCalValue = oNode.Value;
                }
                bCalculated = true;
                //Calculated(this, null);
            }
        }

        public void CalculateUpdateAlisWebService()
        {
            // Get all the Queue details 

            string sUserName = GetInputCalValue("UserName");
            string sToken = GetInputCalValue("Token");
            string sPassword = GetInputCalValue("Password");
            string sLanguageId = GetInputCalValue("LanguageId");
            string sCompanyId = GetInputCalValue("CompanyId");


            string sSend = "<?xml version=\"1.0\" encoding=\"UTF8\"?><Root><XMLHeader><MethodName>Update</MethodName><UserName>$UserName$</UserName><Password>$Password$</Password><LanguageId>$LanguageId$</LanguageId><CompanyId>$CompanyId$</CompanyId></XMLHeader>";
            sSend +="<XMLBody><Updates><Update Name=\"";
            sSend = sSend.Replace("$UserName$", sUserName);
            sSend = sSend.Replace("$Token$", sToken);
            sSend = sSend.Replace("$Password$", sPassword);
            sSend = sSend.Replace("$LanguageId$", sLanguageId);
            sSend = sSend.Replace("$CompanyId$", sCompanyId);
            sSend += sQueryName;
            sSend += "\">";

            foreach (CParam oPar in lParams)
            {
                sSend += "<" + oPar.sName + ">" + oPar.sValue + "</" + oPar.sName + ">";

            }

            sSend += "</Update></Updates></XMLBody></Root>";

            AlisWebService oWs = new AlisWebService();
            string sRet = "";
            try
            {
                sRet = oWs.putAndGetMessage(sSend);
                IniFile oIni = new Ini.IniFile(m_FileSequence.sWorkingFolder + "\\Stats.ini");
                oIni.IniWriteValue("Run-" + m_FileSequence.m_RunNum.ToString(), "CalculateAlisWebService-" + sName, DateTime.Now.ToString());

            }
            catch (Exception e)
            {
                m_FileSequence.sLastError = "Failed to call the AlisWebServices(" + e.Message + ")\r\n";
                IniFile oIni = new Ini.IniFile(m_FileSequence.sWorkingFolder + "\\Stats.ini");
                oIni.IniWriteValue("Run-" + m_FileSequence.m_RunNum.ToString(), "CalculateAlisWebServiceError(" + e.Message + ")-" + sName, DateTime.Now.ToString());
            }

            XmlDocument oXmlDoc = new XmlDocument();
            if (sRet.Length > 0)
            {
                oXmlDoc.LoadXml(sRet);

                foreach (COutput oOut in lOutputs)
                {
                    XmlNode oNode = oXmlDoc.SelectSingleNode(oOut.sValue);
                    if (oNode != null)
                        oOut.sCalValue = oNode.Value;
                }
                bCalculated = true;
                //Calculated(this, null);
            }
        }
        
        public void CalculateUpdateQueryDef()
        {
            CAlisV6MQ.CAlisV6MQ oCAlisV6MQ = new CAlisV6MQ.CAlisV6MQ();

            // Get all the Queue details
            IniFile oIniFile = new IniFile("C:\\Sapiens\\Sequence\\Sequence.ini");


            // Get all the Queue details 
            string sQueueManager = oIniFile.IniReadValue("MQ", "QueueManager");
            string sChannel = oIniFile.IniReadValue("MQ", "Channel");
            string sServer = oIniFile.IniReadValue("MQ", "Server");
            string sRequestQueue = oIniFile.IniReadValue("MQ", "RequestQueue");
            string sResponseQueue = oIniFile.IniReadValue("MQ", "ResponseQueue");

            string sUserName = oIniFile.IniReadValue("QDHeader", "UserName");
            string sToken = oIniFile.IniReadValue("QDHeader", "Token");
            string sPassword = oIniFile.IniReadValue("QDHeader", "Password");
            string sLanguageId = oIniFile.IniReadValue("QDHeader", "LanguageId");
            string sCompanyId = oIniFile.IniReadValue("QDHeader", "CompanyId");


            string sSend = "<?xml version=\"1.0\" encoding=\"UTF8\"?><Root><XMLHeader><MethodName>Update</MethodName><UserName>$UserName$</UserName><Password>$Password$</Password><LanguageId>$LanguageId$</LanguageId><CompanyId>$CompanyId$</CompanyId></XMLHeader><XMLBody><Updates><Update Mode=\"$Mode$\" Name=\"";
            sSend += sQueryName + "\">";

            foreach (CInput oIn in lInputs)
            {
                if (!StandardInput(oIn.sName))
                {
                    sSend += "<" + oIn.sName + ">" + oIn.sCalValue + "</" + oIn.sName + ">";
                }
            }

            sSend += "</Update></Updates></XMLBody></Root>";

            sSend = sSend.Replace("$UserName$", sUserName);
            sSend = sSend.Replace("$Token$", sToken);
            sSend = sSend.Replace("$Password$", sPassword);
            sSend = sSend.Replace("$LanguageId$", sLanguageId);
            sSend = sSend.Replace("$CompanyId$", sCompanyId);
            sSend = sSend.Replace("$Mode$", sMode);

            if ((sQueueManager.Length == 0) || (sChannel.Length == 0) || (sServer.Length == 0) || (sLanguageId.Length == 0) ||
                (sRequestQueue.Length == 0) || (sResponseQueue.Length == 0) || (sUserName.Length == 0)  ||
                (sCompanyId.Length == 0) || (sMode.Length == 0)) 
            {
                // Raise an error 
                 sErrorCode = "2";
                 sErrorMessage = "Missing Inputs";

                 //IniFile oIni = new Ini.IniFile(m_FileSequence.sWorkingFolder + "\\Stats.ini");
                 //oIni.IniWriteValue("Run-" + m_FileSequence.m_RunNum.ToString(), "CalculateUpdateQueryDefError-" + sName, DateTime.Now.ToString());
            }
            else
            {

                oCAlisV6MQ.Init(sServer, sQueueManager, sRequestQueue, sResponseQueue, sChannel);
                string sRet = oCAlisV6MQ.SendAndGetMessage(sSend);
                sLastRunInXml = sSend; sLastRunOutXml = sRet;

                XmlDocument oXmlDoc = new XmlDocument();
                if (sRet.Length > 0)
                {
                    oXmlDoc.LoadXml(sRet);
                    sErrorCode = oXmlDoc.SelectSingleNode("/Root/ReturnCode/text()").Value;
            

                    if (sErrorCode == "2")
                    {
                        sErrorMessage = oXmlDoc.SelectSingleNode("/Root/Reason/Message/text()").Value;
                    }
                    else
                    {
                        sErrorMessage = "";
                        foreach (COutput oOut in lOutputs)
                        {
                            // Need to set the calValue from the input 
                            if (oOut.sValue.Substring(0, 6).ToLower() == "input>")
                            {
                                string[] arrOut = oOut.sValue.Split('>');
                                if (arrOut.Count() == 2)
                                {
                                    CInput oIn = lInputs.Find(element => element.sName == arrOut[1]);
                                    if (oIn != null)
                                        oOut.sCalValue = oIn.sCalValue;
                                }
                            }
                            else
                            {
                                XmlNode oNode = oXmlDoc.SelectSingleNode(oOut.sValue);
                                if (oNode != null)
                                    oOut.sCalValue = oNode.Value;
                            }
                        }
                        bCalculated = true;
                        //Calculated(this, null);
                        }

                    //IniFile oIni = new Ini.IniFile(m_FileSequence.sWorkingFolder + "\\Stats.ini");
                    //oIni.IniWriteValue("Run-" + m_FileSequence.m_RunNum.ToString(), "CalculateUpdateQueryDef-" + sName, DateTime.Now.ToString());

                }
            }
        }

        private bool StandardInput(string sName)
        {
            bool bRet = false;
            if (sName == "QueueManager") bRet = true;
            if (sName == "Channel") bRet = true;
            if (sName == "Server") bRet = true;
            if (sName == "RequestQueue") bRet = true;
            if (sName == "ResponseQueue") bRet = true;
            if (sName == "UserName") bRet = true;
            if (sName == "Token") bRet = true;
            if (sName == "Password") bRet = true;
            if (sName == "LanguageId") bRet = true;
            if (sName == "CompanyId") bRet = true;
            if (sName == "Mode") bRet = true;
            return bRet;
        }

        public string GetResults()
        {
            string sRet="";
            foreach ( COutput oOut in lOutputs)
                sRet += oOut.sName + " , " + oOut.sCalValue + "\r\n";
            return sRet;
        }


        public void Calculate()
        {

            // Chech to see it any inputs need to be set from previously Calculated Setps 
            foreach (CInput oIn in lInputs)
            {
                string[] aIn = oIn.sValue.Split('>');
                if (aIn.Length == 2)
                {
                    string sStep = aIn[0]; string sInput = aIn[1];
                    CStep oSt = m_FileSequence.oSteps.Find(element => element.sName == sStep);
                    if (oSt != null)
                    {
                        if (!oSt.bCalculated)
                        {
                            oSt.Calculate();
                        }

                        COutput oOut = oSt.lOutputs.Find(element => element.sName == sInput);
                        if (oOut != null)
                            oIn.sCalValue = oOut.sCalValue;                        
                    }
                    else
                    {
                        m_FileSequence.sLastError += "Cant find (" + sStep + ") in (" + oIn.sName + ")\r\n";
                    }
                }
                else
                {
                    if (oIn.sValue.Substring(0, 1) == "=")
                    {
                        oIn.sCalValue = CallFunction(oIn.sValue);
                    }
                    else
                    {
                        if (oIn.sValue != "?") 
                            oIn.sCalValue = oIn.sValue;
                    }                    
                }
            }

            // Now check and output values that need to be set 
            foreach (COutput oOut in lOutputs)
            {
                // Need to set the calValue from the input 
                if (oOut.sValue.Substring(0, 6).ToLower() == "input>")
                {
                    string[] arrOut = oOut.sValue.Split('>');
                    if (arrOut.Count() == 2)
                    {
                        CInput oIn = lInputs.Find(element => element.sName == arrOut[1]);
                        if (oIn != null)
                            oOut.sCalValue = oIn.sCalValue;
                    }
                }
            }


            // Now do the actual calculation
            switch (sType)
            {
                case "Constants":
                    foreach (COutput oOut in lOutputs)
                    {
                        oOut.sCalValue = oOut.sValue;
                    }
                    bCalculated = true;
                    break;
                case "QueryDef":
                    CalculateQueryDef();
                    break;

                case "AlisWebService":
                    CalculateAlisWebService();
                    break;

                case "UpdateAlisWebService":
                    CalculateAlisWebService();
                    break;

                case "QueryDefUpdate":
                    CalculateUpdateQueryDef();
                    break;

                case "QueryDefProcess":
                    CalculateQueryDefProcess();
                    break;

                case "IF":
                    CalculateIf();
                    break;
                case "ELSE":
                    m_FileSequence.bIfElseFlag = !m_FileSequence.bIfElseFlag;
                    break;
                case "END IF":
                    m_FileSequence.bIfElseFlag = false;
                    break;

                case "FOR":
                    // Save the start of the for 
                    m_FileSequence.iForStart = Convert.ToInt16(sId)-1;
                    m_FileSequence.iForCount = 0;
                    break;

                case "END FOR":
                    // Save the start of the for 
                    m_FileSequence.iForCount++;
                    if (m_FileSequence.oSteps[m_FileSequence.iForStart].lInputs.Count() > 0)
                    {
                        if (m_FileSequence.iForCount != Convert.ToInt16(m_FileSequence.oSteps[m_FileSequence.iForStart].lInputs[0].sValue))
                            m_FileSequence.iCurrentStep = m_FileSequence.iForStart;
                    }

                    break;
            }
        }

        private void CalculateQueryDefProcess()
        {

            FileSequence oSequence = new FileSequence(sQueryName,m_connection);

            foreach (CStep oSt in oSequence.oSteps)
            {
                foreach (CInput oIn in oSt.lInputs)
                {
                    if (oIn.sValue == "?")
                    {
                        CInput oIn2 = lInputs.Find(element => element.sName == oIn.sName);
                        if (oIn2 != null)
                            oIn.sCalValue = oIn2.sValue;
                    }
                }
            }

            oSequence.Load();
            oSequence.Calculate();

        }

        private string CallFunction(string sName)
        {
            string sRet = "";
            sName = sName.Replace("=", ""); sName = sName.Replace("(", ""); sName = sName.Replace(")", "");
            switch (sName.ToUpper())
            {
                case "GETUNIQUETIN":
                    sRet = GetUniqueTIN();
                    break;
            }
            return sRet;
        }

        private string GetUniqueTIN()
        {
            string sRet = DateTime.Now.ToString( "3ddHHmmss");
            return sRet;
        }
        
        public void CalculateSave()
        {
            m_FileSequence.sLastError = "";
            // First check all the inputs have been calculated 
            foreach (CInput oIn in lInputs)
            {
                if (oIn != null)
                {
                    if (oIn.sValue == "?")
                    {
                        //To Do 
                        //Write Input box
                    }

                    string[] aIn = oIn.sValue.Split('>');
                    if (aIn.Length == 2)
                    {
                        string sStep = aIn[0]; string sInput = aIn[1];
                        CStep oSt = m_FileSequence.oSteps.Find(element => element.sName == sStep);
                        if (oSt != null)
                        {
                            if (!oSt.bCalculated)
                            {
                                oSt.Calculate();
                            }
                            COutput oOut = oSt.lOutputs.Find(element => element.sName == sInput);
                            if (oOut != null)
                                oIn.sCalValue = oOut.sCalValue;
                        }
                        else
                        {
                            m_FileSequence.sLastError += "Cant find (" + sStep + ") in (" + oIn.sName + ")\r\n";
                        }
                    }
                }
            }

            // Now do the actual calculation
            switch (sType)
            {
                case "Constants":
                    foreach (COutput oOut in lOutputs)
                    {
                        oOut.sCalValue = oOut.sValue;
                    }
                    IniFile oIni = new Ini.IniFile(m_FileSequence.sWorkingFolder + "\\Stats.ini");
                    oIni.IniWriteValue("Run-" + m_FileSequence.m_RunNum.ToString(), "Constants-" + sName, DateTime.Now.ToString());

                    //Calculated(this, null);
                    bCalculated = true;
                    break;
                case "QueryDef":
                    CalculateQueryDef();
                    break;

                case "AlisWebService":
                    CalculateAlisWebService();
                    break;

                case "UpdateAlisWebService":
                    CalculateAlisWebService();
                    break;

                case "UpdateQueryDef":
                    CalculateUpdateQueryDef();
                    break;
            }
        }
    }

    public class FileSequence
    {
        public string sLastError;
        public bool bIfElseFlag = false;
        public bool bIsDirty;
        public int m_RunNum;
        public int m_iId;
        private OleDbConnection m_connection;

        public int iCurrentStep;
        public int iForStart;
        public int iForCount;

        public FileSequence()
        {
            dStart = DateTime.Now;
        }

        public FileSequence(OleDbConnection oConnection)
        {
            m_connection = oConnection;
            dStart = DateTime.Now;
        }


        public FileSequence(string sProcessName, OleDbConnection oConnection)
        {
            m_connection = oConnection;
            dStart = DateTime.Now;
            try
            {
                string sSql = "select * from t_api_qd_process where name ='" + sProcessName + "'";
                OleDbCommand command = new OleDbCommand(sSql, m_connection);
                OleDbDataReader oDataReader = command.ExecuteReader();

                if (oDataReader.Read())
                {
                    if (oDataReader["ID"].ToString().Length > 0)
                    {
                        m_iId = Convert.ToInt16(oDataReader["ID"].ToString());
                        Load();
                    }
                }
                oDataReader.Close();
                oDataReader.Dispose();
            }
            catch (Exception ex)
            {
                //sText += ex.Message + " (" + sSql + ")\r\n";
            }

        }



        public string GetProcessName()
        {
            if (bIsDirty)
                return sName + "*";
            else
                return sName;
        }

        public string sWorkingFolder;

        private DateTime dStart;

        public string GetTime()
        {
            return DateTime.Now.Subtract(dStart).ToString();
        }

        public string sName;

        public List<CStep> oSteps = new List<CStep>();

        public CStep FindStep( string sName)
        {
            CStep oStep = oSteps.Find(element => element.sName == sName);
            return oStep;
        }

        private string m_sStartFile;

        public override string ToString()
        {
            string sRet = "FileSequence: Steps(";
            sRet += oSteps.Count() + ") - " + DateTime.Now.Subtract(dStart).ToString() + "\r\n";
            foreach (CStep oStep in oSteps)
                sRet += oStep.ToString();
            return sRet;
        }

        public string sStartFile
        {
            get
            {
                return m_sStartFile;
            }
            set
            {
                CStep oNewStep = new CStep();
                m_sStartFile = value;
            }
        }


        private void AddParams(CStep oStep)
        {
            String sSql = "select * from T_API_QD_PROCESS_STEP_PARAMS where process_id=" + oStep.sProcessId + " and STEP_ID=" + oStep.sId;
            try
            {
                OleDbCommand command = new OleDbCommand(sSql, m_connection);
                OleDbDataReader oDataReader = command.ExecuteReader();

                while (oDataReader.Read())
                {
                    string sInName = oDataReader["NAME"].ToString();
                    string sInValue = oDataReader["PARAM_VALUE"].ToString();
                    string sID = oDataReader["ID"].ToString();
                    switch (oDataReader["PARAMS_TYPE"].ToString())
                    {
                        case "I":
                            if (sInName != null)
                            {
                                CInput oIn = new CInput(sInName, sInValue, sID, oStep);
                                oStep.lInputs.Add(oIn);
                            }

                            break;
                        case "O":
                            if (sInName != null)
                            {
                                COutput oOut = new COutput(sInName, sInValue, sID, oStep);
                                oStep.lOutputs.Add(oOut);
                            }
                            break;
                        case "D":
                            if (sInName != null)
                            {
                                CDisplay oDis = new CDisplay(sInName, sInValue, sID, oStep);
                                oStep.lDisplay.Add(oDis);
                            }
                            break;

                    }

                }
                oDataReader.Close();
                oDataReader.Dispose();
                command.Dispose();

            }
            catch (Exception ex)
            {
                //WriteError(ex.Message + " (" + sSql + ")");
            }
        }

        public void Calculate()
        {
            foreach (CStep oStep in oSteps)
                oStep.Calculate();
        }


        public void Load()
        {
            String sSql = "select t_api_qd_process.name as process, t_api_qd_process_step.ID,t_api_qd_process_step.PROCESS_ID,";
            sSql += "          t_api_qd_process_step.NAME,t_api_qd_process_step.QUERY_NAME,t_api_qd_process_step.STEP_MODE, ";
            sSql += "          t_api_qd_process_step.TYPE sType ";
            sSql += "from t_api_qd_process ";
            sSql += "left outer join t_api_qd_process_step on  t_api_qd_process.id =  t_api_qd_process_step.process_id ";
            sSql += "where t_api_qd_process.id = " + m_iId.ToString() + " ";
            sSql += "order by t_api_qd_process_step.ID";

            try
            {
                OleDbCommand command = new OleDbCommand(sSql, m_connection);
                OleDbDataReader oDataReader = command.ExecuteReader();
                
                while (oDataReader.Read())
                {
                    if (oDataReader["ID"].ToString().Length > 0)
                    {
                        CStep oStep = new CStep(oDataReader, m_connection, this);
                        AddParams(oStep);
                        oSteps.Add(oStep);                            
                    }
                }
                oDataReader.Close();
                oDataReader.Dispose();
                command.Dispose();
            }
            catch (Exception ex)
            {
                //sText += ex.Message + " (" + sSql + ")\r\n";
            }
        }
    }    
}
